package cn.yangliu.nacos.consumer.config;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Type;
import java.util.Collections;

import cn.yangliu.nacos.comm.JsonResult;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.RuntimeJsonMappingException;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import feign.Response;
import feign.Util;
import feign.codec.Decoder;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * The type of nacos.
 *
 * @author 问道于盲
 * @date 2019-12-30
 */
@Component
public class OAuthJacksonDecoder implements Decoder {

    private static final Logger LOGGER = LoggerFactory.getLogger(OAuthJacksonDecoder.class);

    private final ObjectMapper mapper;

    /**
     * constructor
     */
    public OAuthJacksonDecoder() {
        this(Collections.emptyList());
    }

    /**
     * constructor
     *
     * @param modules
     */
    public OAuthJacksonDecoder(Iterable<Module> modules) {
        this(new ObjectMapper().registerModules(modules));
    }

    /**
     * constructor
     *
     * @param mapper
     */
    public OAuthJacksonDecoder(ObjectMapper mapper) {
        LOGGER.info("Using default jackson decoder!");
        this.mapper = mapper;
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.registerModule(new JavaTimeModule());
    }

    /**
     * @see Decoder#decode(Response, Type)
     */
    @Override
    public Object decode(Response response, Type type) throws IOException {
        if (response.status() == 404) {
            return Util.emptyValueOf(type);
        }
        if (response.body() == null) {
            return null;
        }
    /*    byte[] bytes = IOUtils.toByteArray(response.body().asInputStream());

        System.out.println(new String(bytes));*/
        Reader reader = response.body().asReader();
        if (!reader.markSupported()) {
            reader = new BufferedReader(reader, 1);
        }
        try {
            /**
             * Read the first byte to see if we have any data
             */
            reader.mark(1);
            if (reader.read() == -1) {
                /**
                 * Eagerly returning null avoids "No content to map due to
                 * end-of-input"
                 */
                return null;
            }
            reader.reset();
            /**
             * Start Modify
             */
            JsonResult<?> result = mapper.readValue(reader,
                    mapper.constructType(type));
            if (result.getCode()!=200) {
                LOGGER.error("code = {}, message = {}", result.getCode(), result.getMsg());
            }
            /**
             * End Modify
             */
            return result;
        } catch (RuntimeJsonMappingException e) {
            if (e.getCause() instanceof IOException) {
                throw IOException.class.cast(e.getCause());
            }
            throw e;
        }
    }

}

